package com.zmn.oms.dubbo.impl.zmn.serviceprovider.statement;

import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import org.apache.dubbo.config.annotation.Service;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.oms.business.impl.base.AbstractListEsQueryServiceImpl;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.dubbo.dto.zmn.order.AccountAmountDRO;
import com.zmn.oms.dubbo.interfaces.zmn.serviceprovider.statement.AccountAmountRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.aggregations.metrics.ParsedValueCount;
import org.elasticsearch.search.collapse.CollapseBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * @author ：SongWeidong
 * @date ：2020/8/17 15:43
 * @description：结算明细
 */
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class AccountAmountRemoteServiceImpl extends AbstractListEsQueryServiceImpl implements AccountAmountRemoteService {

    private static final Logger logger = LoggerFactory.getLogger(AccountAmountRemoteServiceImpl.class);


    @Resource
    private OrderWorkEsBService orderWorkEsBService;

    // 可提现金额
    @Override
    public ResponseDTO<AccountAmountDRO> accountAmount(Integer spId, String spStatementTime) {

        String groupField = "manageCompanyId";
        // 工单状态
        String queryFieldOrderStatus = "status";
        // 服务商结算状态
        String spStatementStatus = "spStatementStatus";

        // 按照服务商id分组
        TermsAggregationBuilder totalAgg = AggregationBuilders.terms(groupField).field(groupField)
                // 待审核订单数量
                .subAggregation(
                        AggregationBuilders.filter("un_review_filter", QueryBuilders.boolQuery()
                                .must(QueryBuilders.termsQuery(queryFieldOrderStatus,
                                        Lists.newArrayList(OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE,
                                                OrderStatusConsts.WORK_STATUS_COMPLETE, OrderStatusConsts.WORK_STATUS_CHECKOUT)))
                        ).subAggregation(AggregationBuilders.count("un_review_count").field("orderId"))
                )
                // 待结算金额
                .subAggregation(
                        AggregationBuilders.filter("un_account_filter", QueryBuilders.boolQuery()
                                .must(QueryBuilders.termsQuery(queryFieldOrderStatus,
                                        Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ACCOUNT)))
                                .must(QueryBuilders.termQuery(spStatementStatus, GlobalConsts.NO))
                        ).subAggregation(AggregationBuilders.sum("un_account_sum").field("serviceProviderRewardAmount"))
                )
                // 待结算订单数量
                .subAggregation(
                        AggregationBuilders.filter("un_account_count_filter", QueryBuilders.boolQuery()
                                .must(QueryBuilders.termsQuery(queryFieldOrderStatus,
                                        Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ACCOUNT)))
                                .must(QueryBuilders.termQuery(spStatementStatus, GlobalConsts.NO))
                        ).subAggregation(AggregationBuilders.count("un_account_count").field("orderId"))
                )
                // 已结算金额
                .subAggregation(
                        AggregationBuilders.filter("account_filter", QueryBuilders.boolQuery()
                                .must(QueryBuilders.termsQuery(queryFieldOrderStatus,
                                        Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ACCOUNT)))
                                .must(QueryBuilders.termQuery(spStatementStatus, GlobalConsts.YES))
                        ).subAggregation(AggregationBuilders.sum("account_sum").field("spStatementAmount"))
                );
        // 设置过滤条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("platWork", GlobalConsts.PLAT_MARK_YEYX))
                        .must(QueryBuilders.termQuery("manageCompanyId", spId));

        String[] receiveTime = spStatementTime.split(",");
        boolQueryBuilder.must(QueryBuilders.rangeQuery("completeTime").gte(receiveTime[0]).lte(receiveTime[1]));
        NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 10000));
        searchQuery.addAggregation(totalAgg);
        searchQuery.setCollapseBuilder(new CollapseBuilder("manageCompanyId"));

        /*Client client = elasticsearchTemplate.getClient();
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(OMS_ORDER_WORK_INDEX)
                                .setTypes(OMS_ORDER_WORK_TYPE)
                                .setQuery(boolQueryBuilder)
                                .setSize(10000)
                                .addAggregation(totalAgg)
                                .setCollapse(new CollapseBuilder("manageCompanyId"));

        logger.debug("searchRequestBuilder:[{}]", searchRequestBuilder);
        SearchResponse response = searchRequestBuilder.get(TimeValue.timeValueSeconds(5));
        if (response.status() != RestStatus.OK) {
            throw new RuntimeException(String.format("es 查询失败 ，响应:%s", response));
        }*/

        Aggregations aggregations = orderWorkEsBService.getAggregationsByQuery(searchQuery);
        ParsedLongTerms terms = aggregations.get(groupField);
        List<? extends Terms.Bucket> buckets = Objects.requireNonNull(Objects.requireNonNull(terms).getBuckets());

        List<AccountAmountDRO> amountList = buckets.stream().map(bucket -> {

            AccountAmountDRO accountAmountDRO = new AccountAmountDRO();
            Aggregations bucketMap = bucket.getAggregations();

            // 订单数
            ParsedValueCount orderCount = (ParsedValueCount) ((ParsedFilter) bucketMap.get("un_review_filter"))
                    .getAggregations().asMap().get("un_review_count");
            int orderCountValue = (int) orderCount.getValue();

            ParsedSum unAmountSum = (ParsedSum) ((ParsedFilter) bucketMap.get("un_account_filter"))
                    .getAggregations().asMap().get("un_account_sum");
            Long unAmountSumValue = ((Double) unAmountSum.getValue()).longValue();

            ParsedValueCount unAmountCount = (ParsedValueCount) ((ParsedFilter) bucketMap.get("un_account_count_filter"))
                    .getAggregations().asMap().get("un_account_count");
            int unAmountCountValue = (int) unAmountCount.getValue();

            ParsedSum amountSum = (ParsedSum) ((ParsedFilter) bucketMap.get("account_filter"))
                    .getAggregations().asMap().get("account_sum");
            Long amountSumValue = ((Double) amountSum.getValue()).longValue();

            accountAmountDRO.setTotalCount(orderCountValue);
            // 待结算金额 = 金额 - 待结算单数*0.1元
            if(unAmountSumValue > 0){
                unAmountSumValue = unAmountSumValue - unAmountCountValue * 10;
            }
            accountAmountDRO.setUnAccount(unAmountSumValue);
            accountAmountDRO.setAccount(amountSumValue);

            return accountAmountDRO;

        }).collect(Collectors.toList());

        AccountAmountDRO accountAmountDRO = CollectionUtil.isNotNullOrEmpty(amountList) ? amountList.get(0) : new AccountAmountDRO();
        return ResponseDTO.success(accountAmountDRO);

    }



}
